package com.rem.chat.aop.aspect;

import com.rem.chat.aop.annotation.GlobalInterceptor;
import com.rem.chat.common.constants.Constants;
import com.rem.chat.common.errcode.GlobalErrorCodeConstants;
import com.rem.chat.common.exception.ControllerException;
import com.rem.chat.common.utils.JacksonUtil;
import com.rem.chat.common.utils.RedisUtil;
import com.rem.chat.service.dto.UserLoginDTO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;

/**
 * @author: Themberfue
 * @date: 2025/6/5 12:45
 * @description:
 */
@Aspect
@Component
public class GlobalOperationAspect {
    @Resource
    RedisUtil redisUtil;

    @Before("@annotation(com.rem.chat.aop.annotation.GlobalInterceptor)")
    public void interceptorDo(JoinPoint joinpoint) {
        // Step 1. 反射获取被拦截的方法
        Method method = ((MethodSignature) joinpoint.getSignature()).getMethod();

        // Step 2. 获取方法上的 GlobalInterceptor 注解
        GlobalInterceptor interceptor = method.getAnnotation(GlobalInterceptor.class);

        // Step 3. 获取当前请求上下文
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        // Step 4. 校验上下文是否存在
        if (null == attributes) {
            throw new ControllerException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR);
        }

        // Step 5. 获取 request
        HttpServletRequest request = attributes.getRequest();

        // Step 6. 从请求头获取 token
        String token = request.getHeader("token");

        // Step 7. 校验是否需要校验登录/管理员权限
        validateUser(token, interceptor.checkLogin(), interceptor.checkAdmin());
    }

    private void validateUser(String token, boolean checkLogin, boolean checkAdmin) {
        // Step 1. 无需校验
        if (!checkAdmin && !checkLogin) {
            return;
        }

        // Step 2. 校验 token
        if (!StringUtils.hasLength(token)) {
            throw new ControllerException(GlobalErrorCodeConstants.UN_AUTHORIZED);
        }

        // Step 3. 从缓存中获取用户信息
        String userVal = redisUtil.get(Constants.REDIS_KEY_WS_TOKEN + token);

        // Step 4. 校验用户权限
        if (null == userVal) {
            throw new ControllerException(GlobalErrorCodeConstants.UN_AUTHORIZED);
        }

        UserLoginDTO user = JacksonUtil.readValue(userVal, UserLoginDTO.class);

        // Step 5. 校验是否需要验证为管理员
        if (checkAdmin && !user.getIsAdmin()) {
            throw new ControllerException(GlobalErrorCodeConstants.FORBIDDEN);
        }
    }
}
